package com.cgs.query.util

import com.cgs.query.domain.QuerySource
import com.cgs.query.exception.QueryException
import com.codahale.metrics.MetricRegistry

class Utils {

    companion object {

        /**
         * 从字符串中提取出别名和定义名
         */
        fun extractAliasAndDefineName(wholeName: String): AliasAndDefineName {
            val parts = wholeName.split(".")
            return when (true) {
                parts.isEmpty() || parts.size > 2 -> throw QueryException("查询的定义名错误：$wholeName")
                parts.size == 1 -> AliasAndDefineName("", parts[0])
                else -> AliasAndDefineName(parts[0], parts[1])
            }
        }

        /**
         * 将标签名和定义名包装成新的字符串
         */
        fun packageAliasAndDefineName(alias: String, defineName: String): String {
            return if (alias.isBlank()) defineName else "$alias.$defineName"
        }

        fun querySource(querySource: QuerySource?): QuerySource {
            return notNull(querySource, "找不到数据源")
        }

        fun <T> notNull(t: T?, msg: String): T {
            return t ?: throw QueryException(msg)
        }

        fun <T> notNullAndThen(t: T?, then: (t: T) -> Unit) {
            if (t != null) then(t)
        }

        fun <T> nullAndThen(t: T?, then: () -> Unit) {
            if (t == null) then()
        }

        fun <T, R> notNullAndConsume(t: T?, then: (t: T) -> R?): R? {
            return if (t != null)
                then(t)
            else
                null
        }

        fun trueAndThen(check: Boolean, trueRun: () -> Unit) {
            if (check) trueRun()
        }

        fun isNotEmpty(collection: Collection<*>?): Boolean {
            return collection?.isNotEmpty() == true
        }

        fun <T> isNotEmptyAndThen(collection: Collection<T>?, then: (t: Collection<T>) -> Unit) {
            if (isNotEmpty(collection)) then(collection!!)
        }

        fun <T, R> checkAndRun(t: T, check: (t: T) -> Boolean, trueRun: (t: T) -> R?, falseRun: (t: T) -> R? = { null }): R? {
            return if (check(t)) {
                trueRun(t)
            } else {
                falseRun(t)
            }
        }
    }
}

data class AliasAndDefineName(
        val alias: String,
        val defineName: String)